#ifndef LINKED_LIST_H_
#define LINKED_LIST_H_

#include <stdlib.h>

/* Nó da lista ligada */
typedef struct LL
{
	void *data; /* Dado */
	struct LL *next; /* Próximo nó */
	struct LL *previous; /* Nó anterior */
} ll_node;

/* Lista ligada */
typedef struct
{
	ll_node *last; /* Último nó */
	ll_node *first; /* Primeiro nó */
	int lenght; /* Comprimento */
} linked_list;

/* Iterador */
typedef struct
{
	ll_node *node; /* Nó corrente */
	linked_list *ll; /* Lista ligada */
} ll_iterator;

/* Retorna uma nova lista ligada */
linked_list *ll_new();
/* Deleta uma lista ligada
 * A função free_f vai ser usada para deletar os dados */
void ll_delete(void *ll, void free_f(void *));
/* Retorna verdadeiro se a lista estiver vazia */
int ll_is_empty(const linked_list *ll);
/* Retorna o comprimento da lista */
int ll_length(const linked_list *ll);
/* Retorna o index-ésimo elemento da lista */
void *ll_get_index(linked_list *ll, int index);
/* Insere na última posição da lista */
void ll_insert_last(linked_list *ll, void *data);
/* Insere na primeira posição da lista */
void ll_insert_first(linked_list *ll, void *data);
/* Remove a primeira posição da lista */
void ll_remove_first(linked_list *ll, void free_f(void *));
/* Remove a última posição da lista */
void ll_remove_last(linked_list *ll, void free_f(void *));

/* Retorna o iterador da lista */
ll_iterator *ll_get_iterator(linked_list *ll);
/* Incrementa o iterador */
void ll_next(ll_iterator *i);
/* Verifica se o iterador chegou ao fim */
int ll_is_end(const ll_iterator *i);
/* Retorna o dado apontado pelo iterador */
void *ll_get(const ll_iterator *i);
/* Remove o elemento apontado pelo iterador
 * A função free_f é utilizada para deletar o dado */
void *ll_remove(ll_iterator *i, void free_f(void *));


#endif /* LINKED_LIST_H_ */
